package com.lifeonwalden.copula.func;

import com.lifeonwalden.copula.constant.CopulaConstants;

import java.math.BigDecimal;
import java.math.RoundingMode;

public interface ArchimedeanDerivative {
    static BigDecimal claytonInvertNDerivative(BigDecimal x, BigDecimal theta, int order) {
        BigDecimal product = BigDecimal.ONE;
        for (int i = 1; i < order; i++) {
            product = product.multiply(CopulaConstants.MINUS_ONE.divide(theta, 16, BigDecimal.ROUND_DOWN).subtract(BigDecimal.valueOf(i)));
        }

        BigDecimal invertNDerivative = BigDecimal.valueOf(Math.pow(theta.doubleValue(), order - 1)).multiply(product).multiply(CopulaConstants.MINUS_ONE);
        BigDecimal variableProduct = theta.multiply(x);
        if (variableProduct.compareTo(CopulaConstants.MINUS_ONE) < 0) {
            return invertNDerivative;
        } else {
            return invertNDerivative.multiply(
                    BigDecimal.valueOf(Math.pow(1 + variableProduct.doubleValue(), CopulaConstants.MINUS_ONE.divide(theta, 16, RoundingMode.DOWN).doubleValue() - order)));
        }
    }
}
